package com.violet.utils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.violet.domain.dto.app.AOrderDto;
import com.violet.domain.emuns.OrderStatus;
import com.violet.domain.po.*;
import com.violet.domain.result.ResultPage;
import com.violet.domain.search.MyPage;
import com.violet.domain.vo.app.AOrderVo;
import com.violet.mapper.*;
import com.violet.service.manager.impl.MProductServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Stream;

@Component
@RequiredArgsConstructor
public class OrderUtils {

    private final TransitionUtils<AOrderDto, BuyOrder, AOrderVo> orderT;
    private final TransitionUtils<AOrderDto.AOrderProduct, BuyProduct, AOrderVo.AOrderProduct> productT;
    private final TransitionUtils<AOrderDto.AOrderAddress, BuyAddress, AOrderVo.AOrderAddress> addressT;

    private final BuyOrderMapper buyOrderMapper;
    private final BuyProductMapper buyProductMapper;
    private final BuyAddressMapper buyAddressMapper;

    private final RiderMapper riderMapper;
    private final UserMapper userMapper;

    private final MProductServiceImpl productService;

    private final MQUtils mq;

    /**
     * 分页获取当前用户指定状态的订单
     * @param myPage 分页
     * @param status 订单状态
     * @return 分页数据
     */
    public ResultPage<List<AOrderVo>> getOrder(MyPage myPage, OrderStatus status) {
        // 拿到分页
        Page<BuyOrder> page = new Page<>(myPage.getCurrentPage(), myPage.getPageSize());
        buyOrderMapper.selectPage(page, new LambdaUpdateWrapper<BuyOrder>()
                .eq(BuyOrder::getStatus, status)
                .eq(BuyOrder::getUserId, UserContent.getUserId()));

        Stream<AOrderVo> stream = page.getRecords().stream()
            .map(item -> {
                // 封装订单 VO
                AOrderVo vo = orderT.transition(item, AOrderVo.class);
                // 封装商品
                List<BuyProduct> products = buyProductMapper.selectList(new LambdaQueryWrapper<BuyProduct>().eq(BuyProduct::getOrderId, item.getId()));
                vo.setProducts(products.stream().map(product -> productT.transition(product, AOrderVo.AOrderProduct.class)).toList());
                // 封装地址
                BuyAddress address = buyAddressMapper.selectOne(new LambdaQueryWrapper<BuyAddress>().eq(BuyAddress::getOrderId, item.getId()));
                vo.setAddress(addressT.transition(address, AOrderVo.AOrderAddress.class));
                // 封装订单状态
                vo.setStatus(item.getStatus().message);
                // 返回
                return vo;
            });

        return ResultPage.success(stream.toList(), "分页查询", page);
    }

    /**
     * 确认收货
     * @param id 订单 ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ)
    public Boolean confirmReceivingOrder(String id) {
        // 拿到订单数据
        BuyOrder order = buyOrderMapper.getByIdWithPessimisticLock(id);
        if (order == null) throw new RuntimeException("订单不存在");
        if (order.getStatus() != OrderStatus.WAIT_RECEIVING) throw new RuntimeException("订单状态错误");
        // 1.更新订单状态
        order.setStatus(OrderStatus.COMPLETED);
        // 2.更新订单送达时间
        order.setDeliveryTime(LocalDateTime.now());
        // 3.数据入库
        if (buyOrderMapper.updateById(order) != 1) throw new RuntimeException("确认收货失败");
        // 4.更新对应商品库存
        // 4.1 根据订单ID获取下单的商品
        List<BuyProduct> buyProducts = buyProductMapper.selectList(new LambdaQueryWrapper<BuyProduct>().eq(BuyProduct::getOrderId, id));
        // 4.2 遍历商品，更新库存
        Stream<Product> productStream = buyProducts.stream().map(buyProduct -> {
            // 4.3 根据 BuyProduct 的 count 去修改 Product 的 库存（stock） 和 monthlySales（月销售）
            Product product = productService.getById(buyProduct.getProductId());
            product.setStock(product.getStock() - buyProduct.getCount());
            product.setMonthlySales(product.getMonthlySales() + buyProduct.getCount());
            return product;
        });
        // 4.4 批量更新商品库存
        productService.updateBatchById(productStream.toList());
        // 5.更新骑手数据（总接单数和每日接单数）
        riderMapper.update(
            new LambdaUpdateWrapper<Rider>()
                .eq(Rider::getId, order.getRideId())
                .setSql("total_orders = total_orders + 1, today_orders = today_orders + 1")
        );
        // 6.更新对应的用户数据
        userMapper.update(
            new LambdaUpdateWrapper<User>()
                .eq(User::getId, order.getUserId())
                .setSql("order_count = order_count + 1, total_consumption = total_consumption +" + order.getFinalPrice())
        );
        // 7.向后台发送消息
        // @TODO: 使用 RabbitMQ 发送消息，确认收到
        mq.sendCompleted();
        return true;
    }

}
